define(['app', 'json5'], function(app, JSON5) {
    app.controller('CodeGeneratorController', function($timeout, xUtil) {
        var self = this;

        self.parameters = {
            packageName: 'app.auth.bean',
            className: 'User',
            fields: [{
                type: 'String',
                name: 'username'
            }, {
                type: 'String',
                name: 'password'
            }]
        };
        self.template = [
            '<%',
            'var toUpperCase = function(name) {',
            '    return name.substring(0,1).toUpperCase() + name.substring(1);',
            '}',
            '%>package <%=packageName%>;',
            '',
            'import java.io.Serializable;',
            '',
            'public class <%=className%> implements Serializable {',
            '<%_.each(fields, function(field) {%>',
            '    private <%=field.type%> <%=field.name%>;',
            '<%});%><%_.each(fields, function(field) {%>',
            '    public <%=field.type%> get<%=toUpperCase(field.name)%>() {',
            '        return <%=field.name%>;',
            '    }',
            '',
            '    public void set<%=toUpperCase(field.name)%>(<%=field.type%> <%=field.name%>) {',
            '        this.<%=field.name%> = <%=field.name%>;',
            '    }',
            '<%});%>',
            '}'
            ].join('\n');
        self.code = '';
        self.parsable = false;

        var codeEditor = null;

        self.init = function() {
            xUtil.clipboard.copy('#copy');

            codeEditor = ace.edit('code-editor', {
                mode: 'ace/mode/hjson',
                theme: 'ace/theme/chrome',
                fontSize: 14,
                showPrintMargin: false,
                autoScrollEditorIntoView: true,
                enableBasicAutocompletion: true,
                enableSnippets: true,
                enableLiveAutocompletion: true
            });
            codeEditor.getSession().on('changeAnnotation', function(e) {
                // check errors
                $timeout(function() {
                    var annotations = codeEditor.getSession().getAnnotations();
                    var parsable = true;
                    if (!_.isEmpty(annotations)) {
                        if (_.find(annotations, function(annotation) {
                            return annotation.type == 'error';
                        })) {
                            parsable = false;
                        }
                    }
                    if (self.parsable != parsable) {
                        self.parsable = parsable;
                    }
                });
            });
            $timeout(function() {
                codeEditor.setValue(JSON5.stringify(self.parameters, null, 4), -1);
                codeEditor.resize();
            }, 50);
        }

        self.callback = function(height, width) {
            jQuery('.x-page-scope .x-editor').css('height', (height - 79)/2 + 'px');
            jQuery('.x-page-scope .x-editor>pre').css('min-height', (height - 79)/2 + 'px');
            jQuery('.x-page-scope textarea').height((height - 79)/2);
        }

        self.reset = function() {
            self.parameters = {};
            codeEditor.setValue('{}', -1);
            self.code = '';
            self.template = '';
        }

        self.generate = function(valid) {
            if (valid && self.parsable) {
                self.parameters = JSON5.parse(codeEditor.getValue() || '{}');
                self.code = _.template(self.template)(self.parameters);
            }
        }
    });
});
